#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
//#include <boost/asio/read_at.hpp>

#include "mpHttpException.h"
#include "mpHttpGenericConnection.h"
#include "mpLog.h"

namespace MP{
namespace HTTP{
namespace INTERNAL{

HttpGenericConnection::HttpGenericConnection(boost::asio::io_context& io_context)
    :HttpConnection(),_socket(io_context),_connected(false)
{
    _id = MP::RandomUtils::getUUID();
}


//设置或读取最近一次使用HttpConnection的时间
void HttpGenericConnection::setLastUseTime(time_t clock) {
    _lastUseTime = clock;
}

time_t HttpGenericConnection::getLastUseTime() const {
    return _lastUseTime;
}

void HttpGenericConnection::setPoolKey(const std::string& poolKey){
    _poolKey = poolKey;
}

//返回连接在Pool中对应的Key
const std::string& HttpGenericConnection::getPoolKey() const {
    return _poolKey;
}

//返回连接ID，Connection的唯一标识
const std::string& HttpGenericConnection::getId() const {
    return _id;
}

HttpSocket& HttpGenericConnection::getHttpSocket(){
    return _socket;
}

//void HttpGenericConnection::preConnect(const std::string & host){

//}

void HttpGenericConnection::handshakeAsync(func_handshake_callback&& handler) {
    //auto tmp = std::move(handler);
    throw HttpException("http generic connection not implemented handshake_async.");
}

void HttpGenericConnection::writeSomeAsync(const std::vector<boost::asio::const_buffer>& buffers,
                                           func_write_callback&& handler) {

    boost::asio::async_write(_socket, buffers,std::move(handler));
}

//void HttpGenericConnection::readUntilAsync(std::string & input_buffer,
//                                           const std::string & delim,
//                                           func_read_callback&& handler){

//    boost::asio::async_read_until(_socket, boost::asio::dynamic_buffer(input_buffer), delim,std::move(handler));
//}

void HttpGenericConnection::readSomeAsync(const boost::asio::mutable_buffer& buffers,
                                          func_read_callback&& handler){

    boost::asio::async_read(_socket, buffers,boost::asio::transfer_at_least(1),std::move(handler));
}


//取消当前操作
void HttpGenericConnection::cancle(){
    if(_socket.is_open()){
        boost::system::error_code err;

        _socket.cancel(err);
        if (err) {
            MPLOG_ERROR << "tcp connection socket cancel error ." << err.message();
            err.clear();
        }
        else{
#if defined(MAPLE_MODE_DEBUGGING)
            MPLOG_INFO << "tcp connection socket is canceled ( " << getId() << " )";
#endif
        }
    }
    else{
#if defined(MAPLE_MODE_DEBUGGING)
        MPLOG_INFO << "tcp connection socket is not open, cancle OP cancle . ( " << getId() << " )";
#endif
    }
}

//设置已连接
void HttpGenericConnection::changeToConnect(){
    _connected = true;
}

//断开连接
void HttpGenericConnection::disConnected() {

    if(_connected){
        _connected = false;

        if(_socket.is_open()){

            //https://blog.csdn.net/wangzhiyu1980/article/details/45010885
            boost::system::error_code err;
            _socket.shutdown(boost::asio::ip::tcp::socket::shutdown_type::shutdown_both, err);
            if (err) {
                MPLOG_ERROR << "tcp connection socket shutdown error ." << err.message();
                err.clear();
            }
            else{
#if defined(MAPLE_MODE_DEBUGGING)
                MPLOG_INFO << "tcp connection socket is shutdown ( " << getId() << " )";
#endif
            }

            _socket.close(err);
            if (err) {
                MPLOG_ERROR << "tcp connection socket close error ." << err.message();
                err.clear();
            }
            else{
#if defined(MAPLE_MODE_DEBUGGING)
                MPLOG_INFO << "tcp connection socket is closed ( " << getId() << " )";
#endif
            }

        }
        else{
#if defined(MAPLE_MODE_DEBUGGING)
            MPLOG_INFO << "tcp connection socket is not open, disConnected OP skip . ( " << getId() << " )";
#endif
        }

    }
    else{
#if defined(MAPLE_MODE_DEBUGGING)
        MPLOG_INFO << "tcp connection socket is not connected, disConnected OP cancel . ( " << getId() << " )";
#endif
    }
}

//返回连接是否已连接上
bool HttpGenericConnection::isConnected(){
    return _connected && _socket.is_open();
}


//是否为HTTPS加密连接
bool HttpGenericConnection::isSsl() const {
    return false;
}



}   //INTERNAL
}   //HTTP
}   //MP
